using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Windows;
using System.Windows.Media;
using System.Globalization;

namespace KeyboardImageViewer
{
	public class ViewerConfig
	{
		public ViewerConfig()
		{
			this.ImportRules = new List<string>();
            this.DependencyList = new List<KeyValuePair<string, string>>();
		}

		public bool UseSubdirectories { get; set; }
		public bool TrackDuplicates { get; set; }
        public bool TrackImageDuplicates { get; set; }

        public bool SearchFileName { get; set; }
        public bool SearchTags { get; set; }

		public double MainWidth { get; set; }
		public double MainHeight { get; set; }
        public double ImportWidth { get; set; }
        public double ImportHeight { get; set; }
        public double DuplicateWidth { get; set; }
        public double DuplicateHeight { get; set; }

		public List<ImageItem> Images { get; set; }

		public List<string> ImportRules { get; set; }
        public bool DeleteDuplicatesOnImport { get; set; }

        public List<KeyValuePair<string, string>> DependencyList { get; set; }

		public static ViewerConfig FromFiles(string path)
        {
			ViewerConfig result;

			if (File.Exists(path))
			{
				result = new ViewerConfig();

				StreamReader reader = new StreamReader(path);

				string line, variable, value;

				bool readFailed = false;

				try
				{
					while (!String.IsNullOrEmpty(line = reader.ReadLine()) && !readFailed)
					{
						string[] items = line.Split(new char[] { '|' });

						if (items.Length < 2)
						{
							break;
						}

						variable = items[0];
						value = items[1];

						switch (variable)
						{
							case "UseSubdirectories":
								result.UseSubdirectories = bool.Parse(value);
								break;
							case "SearchFileName":
								result.SearchFileName = bool.Parse(value);
								break;
							case "SearchTags":
								result.SearchTags = bool.Parse(value);
								break;
							case "TrackDuplicates":
								result.TrackDuplicates = bool.Parse(value);
								break;
                            case "TrackImageDuplicates":
                                result.TrackImageDuplicates = bool.Parse(value);
                                break;
							case "MainWidth":
								result.MainWidth = double.Parse(value);
								break;
							case "MainHeight":
								result.MainHeight = double.Parse(value);
								break;
							case "ImportWidth":
								result.ImportWidth = double.Parse(value);
								break;
							case "ImportHeight":
                                result.ImportHeight = double.Parse(value);
								break;
                            case "DuplicateWidth":
                                result.DuplicateWidth = double.Parse(value);
                                break;
                            case "DuplicateHeight":
                                result.DuplicateHeight = double.Parse(value);
                                break;
                            case "DeleteDuplicatesOnImport":
                                result.DeleteDuplicatesOnImport = bool.Parse(value);
                                break;
							case "ImportRules":
								int numRules = int.Parse(value);

								for (int i = 0; i < numRules; i++)
								{
									line = reader.ReadLine();
									if (String.IsNullOrEmpty(line))
									{
										readFailed = true;
										break;
									}

									result.ImportRules.Add(line);
								}

								break;
                            case "TagDependencies":
                                int numDepedencies = int.Parse(value);

                                for (int i = 0; i < numDepedencies; i++)
                                {
                                    line = reader.ReadLine();
                                    if (String.IsNullOrEmpty(line))
                                    {
                                        readFailed = true;
                                        break;
                                    }

                                    string[] dependencyParts = line.Split(new char[] { ',' });
                                    if (dependencyParts.Length != 2)
                                    {
                                        readFailed = true;
                                        break;
                                    }

                                    result.DependencyList.Add(new KeyValuePair<string, string>(dependencyParts[0], dependencyParts[1]));
                                }

                                break;
							case "Version":
								break;
							default:
								readFailed = true;
								break;
						}
					}

					result.Images = new List<ImageItem>();
					ImageItem item = null;

					while (line != null && !readFailed)
					{
						item = new ImageItem();

						while (!String.IsNullOrEmpty(line = reader.ReadLine()))
						{
							string[] items = line.Split(new char[] { '|' });

							if (items.Length < 2)
							{
								readFailed = true;
								break;
							}

							variable = items[0];
							value = items[1];

							switch (variable)
							{
								case "Name":
									item.Name = value;
									break;
								case "Rating":
									item.Rating = int.Parse(value);
									break;
								case "Tags":
									item.Tags = StringBag.FromString(value);
									break;
								case "Hash":
									item.Hash = value;
									break;
								case "LastRefreshDate":
									item.LastRefreshDate = XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.Local);
									break;
                                case "TopColor":
                                    break;
                                case "LeftColor":
                                    break;
								default:
									readFailed = true;
									break;
							}
						}

						if (item.Name != null)
						{
							result.Images.Add(item);
						}
					}
				}
				catch (FormatException)
				{
					readFailed = true;
				}

				reader.Close();

				if (readFailed)
				{
					string corruptedFile = path + ".corrupted";

					if (File.Exists(corruptedFile))
					{
						File.Delete(corruptedFile);
					}

					File.Move(path, corruptedFile);
					result = GetDefaultConfig();
					MessageBox.Show("Could not load config file.  Backing up old file to " + corruptedFile + " and creating new config file.");
				}
			}
			else
			{
				result = GetDefaultConfig();
			}

			return result;
		}

		private static ViewerConfig GetDefaultConfig()
		{
			ViewerConfig result = new ViewerConfig();
			result.SearchTags = true;
			result.SearchFileName = true;
			result.Images = new List<ImageItem>();
			result.UseSubdirectories = false;

			return result;
		}
	}
}